<?php

class Tree
{
   /**
      @param $path1,$path2,...   path names OR
      @param $path  array($name1,...) - array of names as first and ONLY $path param
      @param $value  value for path in tree to assign
   */
   public function put($path1/*,$path2,...*/,$value)
   {
      $args = func_get_args();
      $numArgs = count($args);

      assert($numArgs>=2);

      if (is_array($args[0]))
      {
         assert($numArgs==2);
         $args = array_merge($args[0],array($args[1]));
         $numArgs = count($args);
      }

      $branch = &$this->root;
      for ($i=0; $i<$numArgs-2; ++$i)
      {
         $path = $args[$i];
         if (!array_key_exists($path, $branch))
         {
            $branch[$path] = array();
         }
         $branch = &$branch[$path];         
      }
      $branch[$args[$i]] = array();
      $branch[$args[$i]][0] = $args[$numArgs-1];
   }

   public function get($path1/*,$path2,...*/)
   {
      $args = func_get_args();     

      $branch = &$this->root;
      foreach ($args as $path)
      {
         if (!array_key_exists($path,$branch))
         {
            return false;
         }
         $branch = &$branch[$path];
      }
      return $branch;
   }

   /**
      @return  array(name,hierarchy_level,hierarchy_states,parent_path,path,first,last)
   */
   public function toArray()
   {
      $ar = array();
      self::exportToArray($this->root, 0, array(), array(), $ar);
      return $ar;
   }

   

   static private function exportToArray($branch, $level, $parentPath, $states, &$ar)
   {
      $first = true;
      $count = count($branch);
      $i = 0;
      foreach ($branch as $name => $children)
      {
         if (!$name) {
            continue;  //name==0 means value
         }
         $path = array_merge($parentPath,array($name));
         $last = (++$i == $count);
         array_push(
            $ar, 
            array(
               'name' => $name,
               'hierarchy_level' => $level,
               'hierarchy_state' => $states,
               'parent_path' => $parentPath,
               'path' => $path,
               'first' => $first,
               'last' => $last,
               'value' => array_key_exists(0,$children) ? $children[0] : null
            )
         );
         if (is_array($children))
         {
            self::exportToArray(
               $children, 
               $level+1, 
               $path, 
               array_merge($states,array($last)), 
               $ar
            );
         }
         $first = false;
      }
   }

   private $root = array();
};

?>